package com.grape.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.grape.annotation.RedissonLock;
import com.grape.dto.PermissionDTO;
import com.grape.enums.RedisKeyEnums;
import com.grape.redis.service.IRedisService;
import com.grape.utils.StringUtils;
import com.grape.utils.ThreadLocalUtil;
import com.grape.vo.BaseVo;
import com.grape.wrapper.BaseWrapper;
import com.grape.entity.SysPermission;
import com.grape.mapper.SysPermissionMapper;
import com.grape.service.ISysPermissionService;
import lombok.AllArgsConstructor;
import org.apache.logging.log4j.util.Strings;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;

/**
 *
 * 权限表 服务实现类
 *
 * @author  putao
 * @email   2628279194@qq.com
 */
@Service
@AllArgsConstructor
@Transactional(readOnly = true)
public class SysPermissionServiceImpl extends ServiceImpl<SysPermissionMapper, SysPermission> implements ISysPermissionService {

    private final SysPermissionMapper sysPermissionMapper;

    private final ThreadPoolTaskExecutor threadPoolTaskExecutor;

    private final IRedisService redisService;

    /**
     * 分页
     * @param baseVo    统一分页对象
     * @return          权限表集合
     */
    @Override
    public List<SysPermission> listData(BaseVo baseVo) {
        QueryWrapper<SysPermission> wrapper = new BaseWrapper<SysPermission>().init();
        wrapper.like(Strings.isNotBlank(baseVo.getSearch()), "name", baseVo.getSearch());
        wrapper.eq(StringUtils.isNotBlank(baseVo.getColumnName())
                && StringUtils.isNotBlank(baseVo.getSelect()), baseVo.getColumnName(), baseVo.getSelect());
        orderByModifyTimeDesc(wrapper);
        return this.list(wrapper);
    }

    /**
     * 修改
     * @param sysPermission 权限表对象
     */
    @Override
    @Transactional(readOnly = false, rollbackFor = Exception.class)
    public void updateData(SysPermission sysPermission) {
        this.baseUpdate(sysPermission);
        refreshPermissionByUserId(ThreadLocalUtil.getUserId());
    }

    /**
     * 新增
     * @param sysPermission 权限表对象
     * @return              权限表对象
     */
    @Override
    @Transactional(readOnly = false, rollbackFor = Exception.class)
    @RedissonLock(prefix = "refresh_user_permission_", key = "T(com.grape.utils.ThreadLocalUtil).getUserId()")
    public SysPermission insertData(SysPermission sysPermission) {
        SysPermission permission = this.baseInsert(sysPermission);
        refreshPermissionByUserId(ThreadLocalUtil.getUserId());
        return permission;
    }

    /**
     * 删除
     * @param id    单据id
     * @return      删除条数
     */
    @Override
    @Transactional(readOnly = false, rollbackFor = Exception.class)
    public int deleteData(String id) {
        int deleteCount = this.baseDelete(id);
        refreshPermissionByUserId(ThreadLocalUtil.getUserId());
        return deleteCount;
    }

    /**
     * 根据id查询详情
     * @param id    权限id
     * @return      权限对象
     */
    @Override
    public SysPermission detail(String id) {
        return this.getById(id);
    }

    /**
     * 根据角色集合查询权限集合
     * @param roleNameList  角色名称集合
     * @return              权限集合
     */
    @Override
    public List<SysPermission> selectByRoleName(List<String> roleNameList) {
        String permissionDTOListJson = redisService.get(RedisKeyEnums.USER_PERMISSION.join(ThreadLocalUtil.getUserId()));
        if (StringUtils.isNotBlank(permissionDTOListJson)) {
            return new ArrayList<>(JSON.parseArray(permissionDTOListJson, PermissionDTO.class));
        }

        if (CollectionUtil.isNotEmpty(roleNameList)) {
            return sysPermissionMapper.selectByRoleName(roleNameList);
        } else {
            return Collections.emptyList();
        }
    }

    /**
     * 根据用户id查询权限列表
     * @param userId    用户id
     * @return          权限列表
     */
    @Override
    public List<SysPermission> selectByUserId(String userId) {
        String permissionDTOListJson = redisService.get(RedisKeyEnums.USER_PERMISSION.join(ThreadLocalUtil.getUserId()));
        if (StringUtils.isNotBlank(permissionDTOListJson)) {
            return new ArrayList<>(JSON.parseArray(permissionDTOListJson, PermissionDTO.class));
        }
        return lockGetPermissionListByUseId(userId);
    }

    /**
     * 加锁查询权限列表
     * @param userId    用户id
     * @return          权限列表
     */
    @Transactional(readOnly = false, rollbackFor = Exception.class)
    @RedissonLock(prefix = "lock_permission_user_id_", key = "#userId")
    public List<SysPermission> lockGetPermissionListByUseId(String userId) {
        String permissionDTOListJson = redisService.get(RedisKeyEnums.USER_PERMISSION.join(userId));
        if (StringUtils.isNotBlank(permissionDTOListJson)) {
            return new ArrayList<>(JSON.parseArray(permissionDTOListJson, PermissionDTO.class));
        }
        List<SysPermission> permissionList = sysPermissionMapper.selectByUserId(userId);
        redisService.set(RedisKeyEnums.USER_PERMISSION.join(userId), JSON.toJSONString(CollectionUtil.isNotEmpty(permissionList) ? permissionList : Collections.emptyList()));
        return permissionList;
    }

    /**
     * 根据角色id查询权限和全部权限
     * @param roleId                角色id
     * @param allPermissionList     全部权限
     * @return                      权限集合
     */
    @Override
    public List<SysPermission> selectByRoleId(String roleId, List<SysPermission> allPermissionList) throws ExecutionException, InterruptedException {
        CompletableFuture<List<SysPermission>> allPermissionsFuture = CompletableFuture.supplyAsync(() -> this.sysPermissionMapper.selectList(new QueryWrapper<>()), threadPoolTaskExecutor);
        CompletableFuture<List<SysPermission>> permissionsFuture = CompletableFuture.supplyAsync(() -> this.sysPermissionMapper.selectByRoleId(roleId), threadPoolTaskExecutor);
        CompletableFuture<Void> allTasks = CompletableFuture.allOf(allPermissionsFuture, permissionsFuture);
        allTasks.join();
        allPermissionList.addAll(allPermissionsFuture.get());
        return permissionsFuture.get();
    }

    /**
     * 查询全部用户权限
     * @return      权限集合
     */
    @Override
    public List<PermissionDTO> listAllUserPermission() {
        return sysPermissionMapper.listAllUserPermission();
    }

    /**
     * 根据用户id刷新redis权限
     * @param userId    用户id
     * @return          刷新结果
     */
    @Override
    @Transactional(readOnly = false, rollbackFor = Exception.class)
    public boolean refreshPermissionByUserId(String userId) {
        redisService.deleteKey(RedisKeyEnums.USER_PERMISSION.join(userId));
        List<SysPermission> permissionList = sysPermissionMapper.selectByUserId(userId);
        redisService.set(RedisKeyEnums.USER_PERMISSION.join(userId), JSON.toJSONString(CollectionUtil.isNotEmpty(permissionList) ? permissionList : Collections.emptyList()));
        return true;
    }

    /**
     * 根据用户id刷新redis权限
     * @param userIdList    用户id集合
     * @return              刷新结果
     */
    @Override
    @Transactional(readOnly = false, rollbackFor = Exception.class)
    public boolean refreshPermissionByUserIdList(List<String> userIdList) {
        if (CollectionUtil.isEmpty(userIdList)) {
            return true;
        }
        for (String userId : userIdList) {
            refreshPermissionByUserId(userId);
        }
        return false;
    }
}
